package org.veloxbot.api.methods;

import org.veloxbot.api.utils.ColorUtil;

import java.awt.Color;
import java.awt.Rectangle;

import java.awt.image.BufferedImage;

import java.util.List;
import java.util.ArrayList;

/**
 * @author Helborn, Velox
 */
public class Camera {

	public static final Rectangle INNER_COMPASS_BOUNDS = new Rectangle(529, 60, 29, 29);

	/**
	 * Gets the current angle of the compass relative to true north, rotating clockwise. Examples:
	 * <br> - North is 0.
	 * <br> - East is 90.
	 * <br> - South is 180.
	 * <br> - West is 270.
	 *
	 * @return The angle of the compass, or -1 if unable to read compass.
	 * @author HelBorn
	 */
	public static int getCompassAngle() {
		final double radius = (INNER_COMPASS_BOUNDS.width / 2.0) - 1.0;
		final double centerX = INNER_COMPASS_BOUNDS.x + radius;
		final double centerY = INNER_COMPASS_BOUNDS.y + radius;
		final List<Integer> angles = getCompassBlackPoints(centerX + 1, centerY + 1, radius);
		if (angles == null) {
			return -1;
		}
		double angle = angles.get(1) - angles.get(0) > 100 ? angles.get(1) + 10.0 : angles.get(0) < 20 && angles.get(1) > 300 ? angles.get(1) - 10.0 : angles.get(0) + 10.0;
		angle *= Math.PI / 180;
		angle += Math.PI;
		final double curX = (centerX + radius * Math.cos(-angle));
		final double curY = (centerY + radius * Math.sin(-angle));
		return (int) ((Math.atan2(curY - (centerY - radius), curX - centerX) * 2) * 180 / Math.PI);
	}

	/**
	 * Gets the two black pixels from the "N" letter that touch the outer edge
	 * of the compass. The center between those two points is a very accurate
	 * reading of the compass's pointing direction.
	 *
	 * @param x      The x coordinate of the compass.
	 * @param y      The y coordinate of the compass.
	 * @param radius The compass's radius.
	 * @return A list containing the two points, or null if not found.
	 * @author HelBorn
	 */
	private static List<Integer> getCompassBlackPoints(final double x, final double y, final double radius) {
		final BufferedImage game = Game.getImage();
		final List<Integer> angles = new ArrayList<Integer>();
		searcher:
		for (double i = 0; i < 360; i++) {
			final double angle = i * Math.PI / 180;
			for (final int a : angles) {
				if ((i - a) < 8) {
					continue searcher;
				}
			}
			final Color color = new Color(game.getRGB((int) (x + radius * Math.cos(angle)), (int) (y + radius * Math.sin(angle))));
			if (ColorUtil.dist(color, Color.BLACK) < 2) {
				angles.add((int) i);
				if (angles.size() == 2) {
					return angles;
				}
			}
		}
		return null;
	}
}
